package com.kaifamiao.dao;

import com.kaifamiao.entity.Customer;
import com.kaifamiao.utils.DataSourceUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class CustomerDao {

    private static final String SELECT_BASE = "SELECT id, username, password, salt, nickname, reg_date FROM t_customers";
    private static final String SELECT_ONE_BY_ID = SELECT_BASE + " WHERE id = ?";
    private static final String SELECT_ONE_BY_USERNAME = SELECT_BASE + " WHERE username = ?";
    private static final String SELECT_ALL = SELECT_BASE + " ORDER BY id";
    private static final String SELECT_MAX_ID = "SELECT max(id) FROM t_customers";
    private static final String INSERT_ONE = "INSERT INTO t_customers (username, password, salt, nickname, reg_date, id) VALUES (?,?,?,?,?,?)";
    private static final String UPDATE_ONE = "UPDATE t_customers SET username=?, password=?, salt=?, nickname=? WHERE id =?";
    private static final String DELETE_ONE = "DELETE FROM t_customers WHERE id = ?";

    private QueryRunner runner;

    public CustomerDao(){
        super();
        runner = new QueryRunner(DataSourceUtils.getDataSource());
    }

    private Customer wrap(ResultSet rs) throws SQLException{
        Customer c = new Customer();
        c.setId( rs.getInt( "id" ) );
        c.setUsername( rs.getString( "username" ) );
        c.setPassword( rs.getString( "password" ) );
        c.setSalt( rs.getString( "salt" ) );
        c.setNickname( rs.getString( "nickname" ) );
        java.sql.Date date = rs.getDate( "reg_date" );
        LocalDate regDate = date == null ? null : date.toLocalDate();
        c.setRegistrationDate( regDate );
        return c;
    }

    public Customer find(Integer id ) {
        ResultSetHandler<Customer> rsHandler = rs -> {
            if( rs.next() ) {
                Customer c = wrap(rs);
                return c ;
            }
            return null;
        };
        try {
            return runner.query(SELECT_ONE_BY_ID, rsHandler, id );
        } catch (SQLException cause) {
            throw new RuntimeException("查询失败", cause);
        }
    }

    public Customer find(String username) {
        ResultSetHandler<Customer> rsHandler = rs -> {
            if( rs.next() ) {
                Customer c = wrap(rs);
                return c ;
            }
            return null;
        };
        try {
            return runner.query(SELECT_ONE_BY_USERNAME, rsHandler, username);
        } catch (SQLException cause) {
            throw new RuntimeException("查询失败", cause);
        }
    }

    public List<Customer> findAll() {
        ResultSetHandler<List<Customer>> rsHandler = rs -> {
            List<Customer> list = new ArrayList<>();
            while( rs.next() ) {
                Customer c = wrap(rs);
                list.add(c);
            }
            return list;
        };
        try {
            return runner.query(SELECT_ALL, rsHandler);
        } catch (SQLException cause) {
            throw new RuntimeException("查询失败", cause);
        }
    }

    public boolean save(Customer c) {
        LocalDate date = c.getRegistrationDate();
        java.sql.Date regDate = date != null ? java.sql.Date.valueOf(date) : null;
        try {
            Integer maxId = runner.query(SELECT_MAX_ID, rs -> rs.next() ? rs.getInt(1) : null );
            c.setId( maxId == null ? 1 : (maxId+1) );
        } catch (SQLException cause) {
            throw new RuntimeException("获取最大id时发生错误", cause);
        }
        Object[] params = {c.getUsername(),c.getPassword(),c.getSalt(),c.getNickname(), regDate, c.getId()};
        try {
            return runner.update(INSERT_ONE, params) == 1 ;
        } catch (SQLException cause) {
            throw new RuntimeException("保存失败", cause);
        }
    }

    public boolean update(Customer c) {
        Object[] params = {c.getUsername(),c.getPassword(),c.getSalt(),c.getNickname(), c.getId()};
        try {
            return runner.update(UPDATE_ONE, params) == 1 ;
        } catch (SQLException cause) {
            throw new RuntimeException("更新失败", cause);
        }
    }

    public boolean remove(Integer id) {
        try {
            return runner.update(DELETE_ONE, id) == 1 ;
        } catch (SQLException cause) {
            throw new RuntimeException("删除失败", cause);
        }
    }

}
